﻿using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using ZilLion.Core.Unities.UnitiesMethods;
using ZilLion.Service.Core.DapperWrapper;
using ZilLion.Service.Core.Log;
using ZilLion.Service.Core.Snowflake;
using ZilLion.Service.WeChatMall.Domain.CrmProxy;
using ZilLion.Service.WeChatMall.Domain.Entitys.Orders;
using ZilLion.Service.WeChatMall.Domain.Repositorys.Interface.CrmProxy;
using ZilLion.Service.WeChatMall.Domain.Repositorys.Interface.Order;
using ZilLion.Service.WeChatMall.Domain.Responses.CrmProxy;
using ZilLion.Service.WeChatMall.Domain.Services.Interface;

namespace ZilLion.Service.WeChatMall.Domain.Services
{
    public class OrderService : IOrderService
    {
        private readonly IOrderDetailRepository _orderDetailRepository;
        private readonly IOrderMainRepository _orderMainRepository;
        private readonly IOrderSendRepository _orderSendInfoRepository;
        private readonly IOrderSinceInfoRepository _orderSinceInfoRepository;
        private readonly IPrePayOrderDetailRepository _prePayOrderDetailRepository;
        private readonly IPrePayOrderMainRepository _prePayOrderMainRepository;
        private readonly IPrePayOrderSendInfoRepository _prePayOrderSendInfoRepository;
        private readonly IPrePayOrderSinceInfoRepository _prePayOrderSinceInfoRepository;

        public OrderService(IOrderDetailRepository orderDetailRepository, IOrderMainRepository orderMainRepository,
            IOrderSendRepository orderSendInfoRepository, IOrderSinceInfoRepository orderSinceInfoRepository,
            IPrePayOrderMainRepository prePayOrderMainRepository,
            IPrePayOrderDetailRepository prePayOrderDetailRepository,
            IPrePayOrderSendInfoRepository prePayOrderSendInfoRepository,
            IPrePayOrderSinceInfoRepository prePayOrderSinceInfoRepository)
        {
            _orderDetailRepository = orderDetailRepository;
            _orderMainRepository = orderMainRepository;
            _orderSendInfoRepository = orderSendInfoRepository;
            _orderSinceInfoRepository = orderSinceInfoRepository;
            _prePayOrderMainRepository = prePayOrderMainRepository;
            _prePayOrderDetailRepository = prePayOrderDetailRepository;
            _prePayOrderSendInfoRepository = prePayOrderSendInfoRepository;
            _prePayOrderSinceInfoRepository = prePayOrderSinceInfoRepository;
        }

        public OrderCompletedInfoDto SavePrePayOrder(OrderCompletedInfoDto dto)
        {
            var result = new OrderCompletedInfoDto
            {
                MainInfo = new OrderMainInfoEntity(),
                SendInfo = new OrderDeliverySendDto(),
                SinceInfo = new OrderDeliverySinceDto(),
                DetailInfos = new List<OrderDetailDto>()
            };
            if (dto.MainInfo.Sno.IsNullOrEmpty())
            {
                dto.MainInfo.Sno = SnowflakeIdCreater.Instance().GetNextSno();
                dto.MainInfo.Bno = SnowflakeIdCreater.Instance().GetNextId().ToString();
                dto.MainInfo.Billdate = DateTime.Now.GetNowChinaTime();
            }
            dto.MainInfo.UpdatedTime = DateTime.Now.GetNowChinaTime();

            using (var unit = new UnitOfWork())
            {
                // 保存主表信息

                var mainentity =
                    JsonConvert.DeserializeObject<PrePayOrderMainInfoEntity>(JsonConvert.SerializeObject(dto.MainInfo));
                _prePayOrderMainRepository.AddMainInfo(mainentity, unit);

                // 保存订单明细

                IList<PrePayOrderDetailEntity> detailentitys = new List<PrePayOrderDetailEntity>();
                long initsn = 0;
                foreach (var detailDto in dto.DetailInfos)
                {
                    var detailentity = detailDto.AutoConvert<PrePayOrderDetailEntity>();
                    detailentity.DetailSno = dto.MainInfo.Sno + ("000" + initsn.ConverttoRadix34Str(10)).Right(3);
                    detailentitys.Add(detailentity);
                    initsn++;
                }

                _prePayOrderDetailRepository.SaveOrderDetailBatch(detailentitys, dto.MainInfo, unit);
                // 保存收货信息

                OrderDeliverySinceDto savedSinceInfo = null;
                OrderDeliverySendDto savedSendInfo = null;
                switch (dto.MainInfo.DeliveryType)
                {
                    case DeliveryType.Since:
                        var sinceentity =
                            JsonConvert.DeserializeObject<PrePayOrderDeliverySinceEntity>(
                                JsonConvert.SerializeObject(dto.SinceInfo));
                        sinceentity.OrderSno = dto.MainInfo.Sno;
                        _prePayOrderSinceInfoRepository.SaveOrderSinceDelivery(sinceentity, dto.MainInfo, unit);
                        savedSinceInfo = sinceentity;
                        break;
                    case DeliveryType.Send:
                        var sendentity =
                            JsonConvert.DeserializeObject<PrePayOrderDeliverySendEntity>(
                                JsonConvert.SerializeObject(dto.SendInfo));
                        sendentity.OrderSno = dto.MainInfo.Sno;
                        _prePayOrderSendInfoRepository.SaveOrderSendDelivery(sendentity, dto.MainInfo, unit);
                        savedSendInfo = sendentity;
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }

                unit.Complete();
                foreach (var detailentity in detailentitys)
                    result.DetailInfos.Add(detailentity);
                result.MainInfo = dto.MainInfo;
                result.SendInfo = savedSendInfo;
                result.SinceInfo = savedSinceInfo;
            }


            return result;
        }

        public OrderCompletedInfoDto  CashPay(AccCashPayResponse payResult, OrderCompletedInfoDto orderInfo,
            AccInfo accinfo, string passport, PassportType passporttype, string crmHost)
        {
            try
            {
                using (var unit = new UnitOfWork())
                {
                    #region 处理主表信息

                    var maininfo = orderInfo.MainInfo;
                    //以下为本次付款信息

                    maininfo.CrmCash = payResult.QianzhReturn.Accbcxj;
                    maininfo.CrmIncrement = payResult.QianzhReturn.Accbczz;
                    maininfo.CrmRed = payResult.QianzhReturn.Accbchb;
                    //maininfo.CrmIntegral = payResult.Accaddbalance;积分兑换订单时存在

                    //以下为账户信息

                    maininfo.CrmAccountName = accinfo.Accname;
                    maininfo.CrmAccountType = (short) passporttype;
                    maininfo.CrmAccountVoucherNo = passport;
                    _orderMainRepository.AddMainInfo(maininfo, unit);
                    _prePayOrderMainRepository.DeleteOrder(maininfo.Sno, unit);

                    #endregion

                    #region 处理明细

                    IList<OrderDetailEntity> detailentitys = new List<OrderDetailEntity>();
                    foreach (var detail in orderInfo.DetailInfos)
                        detailentitys.Add(detail.AutoConvert<OrderDetailEntity>());
                    _orderDetailRepository.SaveOrderDetailBatch(detailentitys, maininfo, unit);
                    _prePayOrderDetailRepository.RemoveOrderDetailBatch(maininfo.Sno, unit);

                    #endregion

                    #region 处理送货单位

                    if (orderInfo.SinceInfo != null && orderInfo.SinceInfo.OrderSno.IsNotNullOrEmpty())
                    {
                        var sinceInfo = orderInfo.SinceInfo.AutoConvert<OrderDeliverySinceEntity>();
                        _orderSinceInfoRepository.SaveOrderSinceDelivery(sinceInfo, maininfo, unit);
                        _prePayOrderSinceInfoRepository.RemoveBatch(maininfo.Sno, unit);
                    }
                    if (orderInfo.SendInfo != null && orderInfo.SendInfo.OrderSno.IsNotNullOrEmpty())
                    {
                        var sendInfo = orderInfo.SendInfo.AutoConvert<OrderDeliverySendEntity>();
                        _orderSendInfoRepository.SaveOrderSendDelivery(
                            sendInfo, maininfo, unit);
                        _prePayOrderSendInfoRepository.RemoveBatch(maininfo.Sno, unit);
                    }

                    #endregion

                    unit.Complete();
                }

                if (payResult.YwCore == null || !payResult.YwCore.Oprsno.IsNotNullOrEmpty()) return orderInfo;
                var checkurl = $"{crmHost}/ApiV1/CRMYwDzService/Accywrecord_Success?crmsno={payResult.YwCore.Oprsno}";
                HttpHelper.HttpRequestGet<AccWalletSingleResponse>(checkurl,
                    new Dictionary<string, string>
                    {
                        {"passport", passport},
                        {"passporttype", ((int) passporttype).ToString()}
                    },
                    content => content.ReadAsStringAsync().Result);
            }
            catch (Exception e)
            {
                ZilLionLogManager.Instance().Error(e);
                if (payResult.YwCore == null || !payResult.YwCore.Oprsno.IsNotNullOrEmpty()) return orderInfo;
                var checkurl = $"{crmHost}/ApiV1/CRMYwDzService/Accywrecord_Fail?crmsno={payResult.YwCore.Oprsno}";
                HttpHelper.HttpRequestGet<AccWalletSingleResponse>(checkurl,
                    new Dictionary<string, string>
                    {
                        {"passport", passport},
                        {"passporttype", ((int) passporttype).ToString()}
                    },
                    content => content.ReadAsStringAsync().Result);
            }
            return orderInfo;
        }

        public IList<OrderCompletedInfoDto> GetPrePayOrders(long custid)
        {
            var result = new List<OrderCompletedInfoDto>();
            var maininfos = _prePayOrderMainRepository.GetOrders(custid);
            var snolist = maininfos.Select(x => x.Sno).ToList();
            var details = _prePayOrderDetailRepository.GetOrderDetails(snolist);
            var sinceInfos = _prePayOrderSinceInfoRepository.GetOrderSinceDeliveryInfos(snolist);
            var sendInfos = _prePayOrderSendInfoRepository.GetOrderSendDeliveryInfos(snolist);
            foreach (var main in maininfos)
            {
                var dto = new OrderCompletedInfoDto
                {
                    MainInfo = main.AutoConvert<OrderMainInfoEntity>(),
                    DetailInfos = details.Where(x => x.DetailSno.StartsWith(main.Sno))
                        .Select(y => y.AutoConvert<OrderDetailDto>()).ToList()
                };

                if (main.DeliveryType == DeliveryType.Send)
                    dto.SendInfo = sendInfos.FirstOrDefault(x => x.OrderSno == main.Sno);
                else
                    dto.SinceInfo = sinceInfos.FirstOrDefault(x => x.OrderSno == main.Sno);
                result.Add(dto);
            }

            return result;
        }

        public IList<OrderAbstractDto> GetPrePayOrdersAbstract(long custid)
        {
            var result = new List<OrderAbstractDto>();
            var maininfos = _prePayOrderMainRepository.GetOrders(custid);
            var snolist = maininfos.Select(x => x.Sno).ToList();
            var details = _prePayOrderDetailRepository.GetOrderDetails(snolist);
            foreach (var main in maininfos)
            {
                var dto = new OrderAbstractDto
                {
                    Shopname = main.Shopname,
                    DealMy = main.DealMy + main.FeeMy,
                    Sno = main.Sno,
                    ShopId = main.Shopid,
                    BillDate = main.Billdate
                };
                var currentDetails = details.Where(x => x.DetailSno.StartsWith(main.Sno)).ToList();
                var count = currentDetails.Count;
                var abstractinfo = currentDetails.FirstOrDefault()?.Gsname;
                dto.DetailAbstract = count > 1 ? $"{abstractinfo}  等 共 {count} 项" : $"{abstractinfo} 共 {count} 项";
                result.Add(dto);
            }

            return result;
        }

        /// <summary>
        ///     分页获取已付款订单数据
        /// </summary>
        /// <param name="custid"></param>
        /// <param name="minsno"></param>
        /// <param name="pageCount"></param>
        /// <returns></returns>
        public IList<OrderAbstractDto> GetOrdersAbstract(long custid, int pageCount = 15, string minsno = "")
        {
            var result = new List<OrderAbstractDto>();
            var maininfos = _orderMainRepository.GetOrdersByPage(custid, pageCount, minsno);
            var snolist = maininfos.Select(x => x.Sno).ToList();
            var details = _orderDetailRepository.GetOrderDetails(snolist);
            foreach (var main in maininfos)
            {
                var dto = new OrderAbstractDto
                {
                    Shopname = main.Shopname,
                    DealMy = main.DealMy + main.FeeMy,
                    Sno = main.Sno,
                    ShopId = main.Shopid,
                    BillDate = main.Billdate
                };
                var currentDetails = details.Where(x => x.DetailSno.StartsWith(main.Sno)).ToList();
                var count = currentDetails.Count;
                var abstractinfo = currentDetails.FirstOrDefault()?.Gsname;
                dto.DetailAbstract = count > 1 ? $"{abstractinfo}  等 共 {count} 项" : $"{abstractinfo} 共 {count} 项";
                result.Add(dto);
            }

            return result;
        }

        public OrderCompletedInfoDto GetPrePayOrderBySno(string sno)
        {
            var result = new OrderCompletedInfoDto();
            var main = _prePayOrderMainRepository.GetOrderMainBySno(sno);
            var details = _prePayOrderDetailRepository.GetOrderDetails(sno);

            result.MainInfo = main.AutoConvert<OrderMainInfoEntity>();
            result.DetailInfos = details.Select(x => x.AutoConvert<OrderDetailDto>()).ToList();

            if (main.DeliveryType == DeliveryType.Send)
                result.SendInfo = _prePayOrderSendInfoRepository.GetOrderSendDeliveryInfo(sno);
            else
                result.SinceInfo = _prePayOrderSinceInfoRepository.GetOrderSinceDeliveryInfo(sno);

            return result;
        }

        public OrderCompletedInfoDto GetPiedOrderBySno(string sno)
        {
            var result = new OrderCompletedInfoDto();
            var main = _orderMainRepository.GetOrderMainBySno(sno);
            var details = _orderDetailRepository.GetOrderDetails(sno);

            result.MainInfo = main.AutoConvert<OrderMainInfoEntity>();
            result.DetailInfos = details.Select(x => x.AutoConvert<OrderDetailDto>()).ToList();

            if (main.DeliveryType == DeliveryType.Send)
                result.SendInfo = _orderSendInfoRepository.GetOrderSendDeliveryInfo(sno);
            else
                result.SinceInfo = _orderSinceInfoRepository.GetOrderSinceDeliveryInfo(sno);

            return result;
        }

        public void CancelOrderBySno(string sno)
        {
            using (var unit = new UnitOfWork())
            {
                _prePayOrderMainRepository.DeleteOrder(sno, unit);
                _prePayOrderDetailRepository.RemoveOrderDetailBatch(sno, unit);
                _prePayOrderSendInfoRepository.RemoveBatch(sno, unit);
                _prePayOrderSinceInfoRepository.RemoveBatch(sno, unit);
                unit.Complete();
            }
        }

        public IList<OrderCompletedInfoDto> GetPrePayOrders()
        {
            throw new NotImplementedException();
        }
    }
}